import java.io.BufferedReader;

import java.io.FileOutputStream;
import java.io.FileReader;

import java.io.IOException;
import java.io.PrintStream;

import java.util.Scanner;

public class LexicalAnalysis {

	// 关键字
	private String[] keyWords = { "auto", "short", "int", "float", "long",
			"double", "char", "struct", "union", "enum", "typedef", "const",
			"unsigned", "signed", "extern", "register", "static ", "volatile",
			"void ", "if", "else", "switch", "case", "for", "do", "while",
			"goto", "continue", "break", "default", "sizeof", "return" };
	// 运算符
	private String[] operator = { "(", ")", "[", "]", "->", ".", "!", "~",
			"++", "--", "+", "-", "*", "&", "/", "%", "<<", ">>", "<", ">",
			">=", "<=", "==", "!=", "^", "|", "&&", "||", "?", ":", "+=", "-=",
			"*=", "/=", "%=", "&=", "|=", "^=", "<<=", ">=", "=" };

	// 分隔符
	private String[] boundary = { ",", ";", "\"", "\"", "\'\'" };
	// 保留字
	private String[] reservedWord = { "include", "main", "printf", "define",
			"stdio", "void" };

	private static String tempString = "";// 暂时存放需要判断的字符
	private static String otherString = "";// 不能判断的其他字符
	private char tempChar;// 从一行中读取的临时字符
	private static String result = "";// 最终的分析结果

	// 判断是不是数字
	public void IsDigit(int count) {// 数值类型判断
		if (tempString != "") {
			Object tempDouble = null;
			if (tempString.charAt(0) >= '0' && tempString.charAt(0) <= '9') {
				tempDouble = Double.parseDouble(tempString);
				if (tempDouble != null
						&& (tempDouble + "").length() == tempString.length()) {
					result += tempString + "\t" + "78" + "\t" + count + "\n";
				} else {
					if (IsKeyWord(tempString)) {
						result += count + "\n";
					} else {
						result += tempString + "\t\t" + "常数" + "\t\t\t" + count
								+ "\n";
					}
				}
			} else {
				if (IsKeyWord(tempString)) {
					result += count + "\n";
				} else if (IsReservedWord(tempString)) {
					result += count + "\n";
				} else {
					result += tempString + "\t\t" + "变量" + "\t\t\t" + count
							+ "\n";
				}
			}
		}
	}

	// 判断是不是关键字
	public boolean IsKeyWord(String string) {
		if (string != "") {
			for (int i = 0; i < keyWords.length; i++) {
				if (string.equals(keyWords[i])) {
					result += string + "\t\t" + "关键字" + "\t\t";
					return true;
				}
			}
		}
		return false;
	}

	// 保留字
	public boolean IsReservedWord(String string) {
		if (string != "") {
			for (int i = 0; i < reservedWord.length; i++) {
				if (string.equals(reservedWord[i])) {
					result += string + "\t" + "保留字" + "\t\t";
					return true;
				}
			}
		}
		return false;
	}

	// 判断是不是运算符
	public boolean IsOperator(String string) {
		if (string != "") {
			for (int i = 0; i < operator.length; i++) {
				if (string.equals(operator[i])) {
					result += string + "\t\t" + "运算符" + "\t\t";
					return true;
				}
			}
		}
		return false;
	}

	// 判断是不是分隔符
	public boolean IsBoundary(String string) {
		if (string != "") {
			for (int i = 0; i < boundary.length; i++) {
				if (string.equals(boundary[i])) {
					result += string + "\t\t" + "分隔符" + "\t\t";
					return true;
				}
			}
		}
		return false;
	}

	public boolean Iscontained(String string) {// 判断字符串是不是包含在运算符
		if (string != "") {
			for (int i = 0; i < operator.length; i++) {
				if (operator[i].equals(string))
					return true;
			}
		}
		return false;
	}

	public void lexicalAnalysis(String targetString, int count) {// 分析函数
		targetString = targetString.trim();
		for (int i = 0; i < targetString.length(); i++) {
			tempChar = targetString.charAt(i);
			if ((tempChar >= 'a' && tempChar <= 'z')
					|| (tempChar >= 'A' && tempChar <= 'Z')) {
				if (otherString != "") {
					if (IsBoundary(otherString) || IsOperator(otherString)) {
						result += count + "\n";
					} else {
						result += otherString + "\t\t" + count + "\n";
					}
					otherString = "";
				}
				tempString += tempChar;
			} else if ((tempChar >= '0' && tempChar <= '9') || tempChar == '.') {
				if (otherString != "") {
					if (IsBoundary(otherString) || IsOperator(otherString)) {
						result += count + "\n";
					} else {
						result += otherString + "\t\t" + count + "\n";
					}
					otherString = "";
				}
				tempString += tempChar;
			} else if (tempChar == ' ') {
				IsDigit(count);
				if (otherString != "") {
					if (IsBoundary(otherString) || IsOperator(otherString)) {
						result += count + "\n";
					} else {
						result += otherString + "\t\t" + count + "\n";
					}
					otherString = "";
				}
				tempString = "";
			} else {
				IsDigit(count);
				String otherTmp = otherString;
				otherString += tempChar;
				if (Iscontained(otherString) && otherString.length() > 1) {
					if (IsOperator(otherString)) {
						result += count + "\n";
					}
					otherString = "";
				} else if (!Iscontained(otherString)
						&& otherString.length() > 1) {
					if (otherTmp != "") {
						if (IsBoundary(otherTmp) || IsOperator(otherTmp)) {
							result += count + "\n";
						} else {
							result += otherTmp + "\t\t" + count + "\n";
						}
					}
					if (IsBoundary(tempChar + "") || IsOperator(tempChar + "")) {
						result += count + "\n";
					} else {
						result += tempChar + "" + "\t\t" + count + "\n";
					}
					otherString = "";
				} else if (!Iscontained(tempChar + "")) {
					if (IsBoundary(tempChar + "")) {
						result += count + "\n";
					} else {
						result += tempChar + "\t\t" + "其他字符" + "\t\t" + count
								+ "\n";
					}
					otherString = "";
				}
				tempString = "";
			}
		}
	}

	// 打开 C文件
	public void openCFile(String fileName) throws IOException {
		int count = 1;
		BufferedReader br = new BufferedReader(new FileReader(fileName));
		String targetString = br.readLine();
		while (targetString != null) {
			lexicalAnalysis(targetString, count);
			count++;
			targetString = br.readLine();
		}
		br.close();
	}

	public static void main(String[] args) throws IOException {
		LexicalAnalysis lA = new LexicalAnalysis();
		Scanner sc = new Scanner(System.in);

		System.out.println("Input the input file name and out put file name, and press enter bettween them:");
		String fileName = sc.next();
		lA.openCFile(fileName);
		String outFileName = sc.next();
		PrintStream ps = new PrintStream(new FileOutputStream(outFileName));
		ps.println("字符（串）" + "\t" + "字符类型" + "\t\t" + "行号");
		ps.print(result.toString());

		System.out.println(result);

	}

}
